00001
00002
00003
00004 //
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 //
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044 #ifndef HEAP_ARRAY_H
00045 #define HEAP_ARRAY_H
00046
00047
00048
00049
00050 namespace common_structures {
00051
00052
00053
00054
00055 template <class T, class CmpT = std::less<T> >
00056 class heap_array
00057 {
00058 public:
00059
00060 struct heap_is_locked { };
00061
00062
00063
00064
00065 heap_array() : m_Locked(false) { }
00066
00067 void clear();
00068
00069 void reserve(size_t Size);
00070 size_t size() const;
00071
00072 bool empty() const;
00073 bool locked() const;
00074 bool removed(size_t i) const;
00075 bool valid(size_t i) const;
00076
00077 const T & top() const;
00078 const T & peek(size_t i) const;
00079 const T & operator [] (size_t i) const;
00080
00081 size_t push(const T & Elem);
00082
00083 void pop();
00084 void erase(size_t i);
00085 void update(size_t i, const T & Elem);
00086
00087 protected:
00088
00089 struct linker {
00090 linker(const T & Elem, size_t i) : m_Elem(Elem), m_Indice(i) { }
00091
00092 T m_Elem;
00093 size_t m_Indice;
00094 };
00095
00096 typedef typename std::vector<linker> linked_heap;
00097 typedef typename std::vector<size_t> finder;
00098
00099 void Adjust(size_t i);
00100 void Swap(size_t a, size_t b);
00101 bool Less(const linker & a, const linker & b) const;
00102
00103 linked_heap m_Heap;
00104 finder m_Finder;
00105 CmpT m_Compare;
00106 bool m_Locked;
00107 };
00108
00109
00110
00111
00112
00113
00114
00115
00116 template <class T, class CmpT>
00117 inline void heap_array<T, CmpT>::clear() {
00118 m_Heap.clear();
00119 m_Finder.clear();
00120 m_Locked = false;
00121 }
00122
00123
00124 template <class T, class CmpT>
00125 inline bool heap_array<T, CmpT>::empty() const {
00126 return m_Heap.empty();
00127 }
00128
00129
00130 template <class T, class CmpT>
00131 inline bool heap_array<T, CmpT>::locked() const {
00132 return m_Locked;
00133 }
00134
00135
00136 template <class T, class CmpT>
00137 inline void heap_array<T, CmpT>::reserve(size_t Size) {
00138 m_Heap.reserve(Size);
00139 m_Finder.reserve(Size);
00140 }
00141
00142
00143 template <class T, class CmpT>
00144 inline size_t heap_array<T, CmpT>::size() const {
00145 return m_Heap.size();
00146 }
00147
00148
00149 template <class T, class CmpT>
00150 inline const T & heap_array<T, CmpT>::top() const {
00151
00152 assert(! empty());
00153
00154 return m_Heap.front().m_Elem;
00155 }
00156
00157
00158 template <class T, class CmpT>
00159 inline const T & heap_array<T, CmpT>::peek(size_t i) const {
00160
00161 assert(! removed(i));
00162
00163 return (m_Heap[m_Finder[i]].m_Elem);
00164 }
00165
00166
00167 template <class T, class CmpT>
00168 inline const T & heap_array<T, CmpT>::operator [] (size_t i) const {
00169 return peek(i);
00170 }
00171
00172
00173 template <class T, class CmpT>
00174 inline void heap_array<T, CmpT>::pop() {
00175 m_Locked = true;
00176
00177
00178 assert(! empty());
00179
00180 Swap(0, size() - 1);
00181 m_Heap.pop_back();
00182 Adjust(0);
00183 }
00184
00185
00186 template <class T, class CmpT>
00187 inline size_t heap_array<T, CmpT>::push(const T & Elem) {
00188 if (m_Locked)
00189 throw heap_is_locked();
00190
00191 size_t Id = size();
00192 m_Finder.push_back(Id);
00193 m_Heap.push_back(linker(Elem, Id));
00194 Adjust(Id);
00195
00196 return Id;
00197 }
00198
00199
00200 template <class T, class CmpT>
00201 inline void heap_array<T, CmpT>::erase(size_t i) {
00202 m_Locked = true;
00203
00204
00205 assert(! removed(i));
00206
00207 size_t j = m_Finder[i];
00208 Swap(j, size() - 1);
00209 m_Heap.pop_back();
00210 Adjust(j);
00211 }
00212
00213
00214 template <class T, class CmpT>
00215 inline bool heap_array<T, CmpT>::removed(size_t i) const {
00216 return (m_Finder[i] >= m_Heap.size());
00217 }
00218
00219
00220 template <class T, class CmpT>
00221 inline bool heap_array<T, CmpT>::valid(size_t i) const {
00222 return (i < m_Finder.size());
00223 }
00224
00225
00226 template <class T, class CmpT>
00227 inline void heap_array<T, CmpT>::update(size_t i, const T & Elem) {
00228
00229 assert(! removed(i));
00230
00231 size_t j = m_Finder[i];
00232 m_Heap[j].m_Elem = Elem;
00233 Adjust(j);
00234 }
00235
00236
00237 template <class T, class CmpT>
00238 inline void heap_array<T, CmpT>::Adjust(size_t i) {
00239 size_t j;
00240
00241
00242 for (j = i; (j > 0) && (Less(m_Heap[(j - 1) / 2], m_Heap[j])); j = ((j - 1) / 2))
00243 Swap(j, (j - 1) / 2);
00244
00245
00246 for (i = j; (j = 2 * i + 1) < size(); i = j) {
00247 if ((j + 1 < size()) && (Less(m_Heap[j], m_Heap[j + 1])))
00248 ++j;
00249
00250 if (Less(m_Heap[j], m_Heap[i]))
00251 return;
00252
00253 Swap(i, j);
00254 }
00255 }
00256
00257
00258 template <class T, class CmpT>
00259 inline void heap_array<T, CmpT>::Swap(size_t a, size_t b) {
00260 std::swap(m_Heap[a], m_Heap[b]);
00261
00262
00263 (size_t &) (m_Finder[(m_Heap[a].m_Indice)]) = a;
00264 (size_t &) (m_Finder[(m_Heap[b].m_Indice)]) = b;
00265 }
00266
00267
00268 template <class T, class CmpT>
00269 inline bool heap_array<T, CmpT>::Less(const linker & a, const linker & b) const {
00270 return m_Compare(a.m_Elem, b.m_Elem);
00271 }
00272
00273
00274
00275
00276 };
00277
00278 #endif